package com.xiaoxx.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.BulkResponse;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.indices.CreateIndexResponse;
import co.elastic.clients.elasticsearch.indices.ElasticsearchIndicesClient;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoxx.common.base.ESVo;
import com.xiaoxx.constants.XzqhCode2023;
import com.xiaoxx.mapper.CodeXzqh2023Mapper;
import com.xiaoxx.model.entity.es.CodeXzqh2023;
import com.xiaoxx.model.vo.es.CodeXzqhVo;
import com.xiaoxx.service.CodeXzqh2023Service;
import com.xiaoxx.utils.EsUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author HX
 * @since 2024-03-19
 */
@Service
@Slf4j
public class CodeXzqh2023ServiceImpl extends ServiceImpl<CodeXzqh2023Mapper, CodeXzqh2023> implements CodeXzqh2023Service {
    @Autowired
    public ElasticsearchClient client;

//    @PostConstruct
//    public void initEs() throws IOException {
//        ElasticsearchIndicesClient indices = client.indices();
//        boolean hotel = indices.exists(e -> e.index(XzqhCode2023.XZQX_INDEX)).value();
//        if (!hotel) {
//            CreateIndexResponse products = client.indices().create(c -> c
//                    .index(XzqhCode2023.XZQX_INDEX)
//                    .mappings(m -> m
//                            .properties("code", builder -> builder.keyword(t -> t))
//                            .properties("name", builder -> builder.keyword(t -> t))
//                            .properties("nameFull", builder -> builder.text(t -> t.analyzer("ik_max_word")))
//                            .properties("provinceCode", builder -> builder.keyword(t -> t))
//                            .properties("provinceName", builder -> builder.keyword(t -> t))
//                            .properties("cityCode", builder -> builder.keyword(t -> t))
//                            .properties("cityName", builder -> builder.keyword(t -> t))
//                            .properties("districtCode", builder -> builder.keyword(t -> t))
//                            .properties("districtName", builder -> builder.keyword(t -> t))
//                            .properties("streetCode", builder -> builder.keyword(t -> t))
//                            .properties("streetName", builder -> builder.keyword(t -> t))
//                            .properties("level", builder -> builder.integer(t -> t))
//                    )
//                    //设置分片   ,numberOfShards分片     ,Replicas副本
//                    .settings((s) -> s.numberOfShards("1").numberOfReplicas("2")));
//            System.out.println("创建索引成功=" + products.acknowledged());
//
//            addXzqhData();
//        }
//    }

    private void addXzqhData() throws IOException {
        int batchSize = 1000; // 每次查询的数量
        int total = count();
        int totalPage = count() / batchSize; // 计算总页数
        totalPage = total % batchSize != 0 ? totalPage + 1 : totalPage;
        for (int j = 1; j <= totalPage; j++) {
            Page<CodeXzqh2023> page = page(new Page<>(j, batchSize));
            List<CodeXzqh2023> list = page.getRecords();
            // 处理每一批查询出来的数据
            //组装BulkOperation
            List<BulkOperation> collect = list.stream().map(i -> BulkOperation.of(b -> b.index(ix -> ix
                    .id(String.valueOf(i.getCode()))
                    .document(i)))
            ).collect(java.util.stream.Collectors.toList());
            //批量插入
            BulkResponse hotel = client.bulk(i -> i
                    .index(XzqhCode2023.XZQX_INDEX)
                    .operations(collect)
            );
            System.out.println("数据添加成功:" + hotel.items());
        }
    }

    @Override
    public List<CodeXzqhVo> getInfoByLevel(String name, Integer level) throws IOException {
        SearchRequest request = SearchRequest.of(i -> i
                .index(XzqhCode2023.XZQX_INDEX)
                .query(q -> q
                        .bool(t ->
                                {
                                    t.must(m1 -> m1.term(t1 -> t1.field("level").value(level)));
                                    if (StringUtils.hasLength(name)) {
                                        t.must(m -> m.multiMatch(m1 -> m1.fields("name", "nameFull").query(name)));
                                    }
                                    return t;
                                }
                        )
                )
                .from(0)
                .size(1000)
        );
        SearchResponse<CodeXzqhVo> search = client.search(request, CodeXzqhVo.class);
        List<CodeXzqhVo> collect = search.hits().hits().stream().map(i -> i.source()).collect(Collectors.toList());
        return collect;
    }

    @Override
    public ESVo getInfoByCode(String code, Integer level, Integer from, Integer size) throws IOException {
        SearchRequest request = SearchRequest.of(i -> i
                .index(XzqhCode2023.XZQX_INDEX)
                .query(q -> q
                        .bool(t -> t
                                .must(m1 -> {
                                    switch (level) {
                                        case 1:
                                            m1.term(m11 -> m11.field("provinceCode").value(code));
                                            break;
                                        case 2:
                                            m1.term(m11 -> m11.field("cityCode").value(code));
                                            break;
                                        case 3:
                                            m1.term(m11 -> m11.field("districtCode").value(code));
                                            break;
                                        case 4:
                                            m1.term(m11 -> m11.field("streetCode").value(code));
                                            break;
                                    }
                                    return m1;
                                })
                                .must(m2 -> {
                                    switch (level) {
                                        case 1:
                                            m2.term(m11 -> m11.field("level").value(level + 1));
                                            break;
                                        case 2:
                                            m2.term(m11 -> m11.field("level").value(level + 1));
                                            break;
                                        case 3:
                                            m2.term(m11 -> m11.field("level").value(level + 1));
                                            break;
                                        case 4:
                                            m2.term(m11 -> m11.field("level").value(level + 1));
                                            break;
                                    }
                                    return m2;
                                })
                        )
                )
                .from(from)
                .size(size));

        SearchResponse<CodeXzqhVo> search = client.search(request, CodeXzqhVo.class);
        EsUtil.printDSL(client._transport(), request);
        List<CodeXzqhVo> collect = search.hits().hits().stream().map(i -> i.source()).collect(Collectors.toList());
        return new ESVo(search.hits().total().value(), collect);
    }

    @Override
    public ESVo getChildInfoByCode(String code, String name, Integer from, Integer size) throws IOException {
        SearchRequest request = SearchRequest.of(i -> i
                .index(XzqhCode2023.XZQX_INDEX)
                .query(q -> q
                        .bool(t -> {
                            t.must(m1 -> m1.multiMatch(m -> m.fields("name", "nameFull").query(name)));
                            if (StringUtils.hasLength(code)) {
                                t.must(m2 -> m2.term(m -> m.field("provinceCode").value(code)));
                            }
                            return t;
                        })
                )
                .from(from)
                .size(size));
        SearchResponse<CodeXzqhVo> search = client.search(request, CodeXzqhVo.class);
        EsUtil.printDSL(client._transport(), request);
        List<CodeXzqhVo> collect = search.hits().hits().stream().map(i -> i.source()).collect(Collectors.toList());
        return new ESVo(search.hits().total().value(), collect);
    }
}
